﻿
using Newtonsoft.Json;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using UnityEngine.Networking;
using XFGameFramework.Localization;


public enum TranslateType
{

    [Tooltip("仅翻译目标语言中字符串为空的配置")]
    Empty,
    [Tooltip("翻译所有配置")]
    All
}

public enum TranslateState
{
    [Tooltip("等待")]
    Wait,
    [Tooltip("翻译中")]
    InTranslation,
    [Tooltip("完成")]
    Completed
}

#if UNITY_6000_2_OR_NEWER
public class TranslateLanguageInfoTreeViewItem : TreeViewItem<int>
#else
public class TranslateLanguageInfoTreeViewItem : TreeViewItem
#endif

{
    public LanguageInfo languageInfo;

    public TranslateLanguageInfoTreeViewItem(LanguageInfo languageInfo) : base(languageInfo.id, 0)
    {
        this.languageInfo = languageInfo;
    }

}

public class TranslateLanguageInfo
{
    public LanguageInfo languageInfo;

    public TranslateState state;

    private MultiLanguageConfigs multiLanguageConfigs;
    private SystemLanguage from;
    private SystemLanguage to;

    private UnityWebRequest request;

    public TranslateAPI api;


    public BaiduTranslateResult baidu_result;

    public YoudaoTranslateResult youdao_result;

    private int retry_count;

    public TranslateLanguageInfo(LanguageInfo languageInfo, MultiLanguageConfigs multiLanguageConfigs, SystemLanguage from, SystemLanguage to)
    {
        this.languageInfo = languageInfo;
        state = TranslateState.Wait;

        this.multiLanguageConfigs = multiLanguageConfigs;
        this.from = from;
        this.to = to;

        baidu_result = null;
        retry_count = 0;
    }


    public void Translate(TranslateAPI api, bool need_intervene, string vocab_id)
    {
        if (state != TranslateState.Wait) return;

        this.api = api;

        state = TranslateState.InTranslation;

        LanguageConfig languageConfig = multiLanguageConfigs.GetLanguageConfigData(from);
        string content = languageConfig.GetLanguageInfo(languageInfo.id).str;

        switch (api)
        {
            case TranslateAPI.Baidu:
                request = TranslateController.TranslateBaidu(from, to, content, need_intervene ? 1 : 0);
                break;
            case TranslateAPI.Youdao:
                request = TranslateController.TranslateYoudao(from, to, content, vocab_id);
                break;
        }

    }

    public void Update()
    {
        if (request == null) return;

        if (state != TranslateState.InTranslation) return;

        if (request.isDone)
        {
            state = TranslateState.Completed;

            switch (api)
            {
                case TranslateAPI.Baidu:

                    baidu_result = JsonConvert.DeserializeObject<BaiduTranslateResult>(request.downloadHandler.text);

                    if (baidu_result != null && !baidu_result.isError)
                    {
                        languageInfo.str = baidu_result.result;
                        multiLanguageConfigs.GetLanguageConfigData(to).Save();
                    }

                    bool limit = baidu_result != null && baidu_result.error_code == "54003";

                    if (limit || baidu_result == null)
                    {
                        if (retry_count < 10)
                        {
                            retry_count++;
                            // 说明访问频率受限  可以再试一次
                            state = TranslateState.Wait;
                            baidu_result = null;
                        }
                    }

                    break;
                case TranslateAPI.Youdao:

                    youdao_result = JsonConvert.DeserializeObject<YoudaoTranslateResult>(request.downloadHandler.text);

                    if (youdao_result != null && !youdao_result.isError)
                    {
                        languageInfo.str = youdao_result.result;
                        multiLanguageConfigs.GetLanguageConfigData(to).Save();
                    }

                    if (youdao_result != null)
                    {
                        if (youdao_result.errorCode == "411" || youdao_result.errorCode == "412")
                        {
                            if (retry_count < 10)
                            {
                                retry_count++;
                                // 说明访问频率受限  可以再试一次
                                state = TranslateState.Wait;
                                youdao_result = null;
                            }
                        }
                    }
                    else
                    {
                        if (retry_count < 10)
                        {
                            retry_count++;
                            // 说明访问频率受限  可以再试一次
                            state = TranslateState.Wait;
                            youdao_result = null;
                        }
                    }

                    break;
            }

        }
    }

    public bool IsError()
    {
        switch (api)
        {
            case TranslateAPI.Baidu:

                if (state == TranslateState.Completed)
                {
                    if (baidu_result == null) return true;
                    if (baidu_result.isError) return true;
                }

                break;
            case TranslateAPI.Youdao:

                if (state == TranslateState.Completed)
                {
                    if (youdao_result == null) return true;
                    if (youdao_result.isError) return true;
                }

                break;
        }

        return false;
    }


    public void Retry()
    {
        retry_count = 0;
        state = TranslateState.Wait;

        baidu_result = null;
        youdao_result = null;
    }
}

#if UNITY_6000_2_OR_NEWER
public class TranslateLanguageInfoListTree : TreeView<int>
#else
public class TranslateLanguageInfoListTree : TreeView
#endif

{

    private MultiLanguageConfigs multiLanguageConfigs;
    private List<LanguageInfo> languageInfos;
    private SystemLanguage from;
    private SystemLanguage to;

    private GUIStyle labelStyle = null;

    private TranslateAPI api;

    // 术语表
    private bool need_intervene = true;

    // 术语表id
    private string vocab_id;


    private Dictionary<int, TranslateLanguageInfo> translateInfos = new Dictionary<int, TranslateLanguageInfo>();

    #region 重写方法

    internal static MultiColumnHeaderState CreateDefaultMultiColumnHeaderState()
    {
        return new MultiColumnHeaderState(GetColumns());
    }
    private static MultiColumnHeaderState.Column[] GetColumns()
    {
        var retVal = new MultiColumnHeaderState.Column[]
        {
                new MultiColumnHeaderState.Column(),
                new MultiColumnHeaderState.Column(),
                new MultiColumnHeaderState.Column(),
                new MultiColumnHeaderState.Column(),
                new MultiColumnHeaderState.Column(),
                new MultiColumnHeaderState.Column(),
            };
        retVal[0].headerContent = new GUIContent("ID", "语言配置唯一标识");
        retVal[0].minWidth = 50;
        retVal[0].width = 100;
        retVal[0].maxWidth = 200;
        retVal[0].headerTextAlignment = TextAlignment.Left;
        retVal[0].canSort = false;
        retVal[0].autoResize = true;

        retVal[1].headerContent = new GUIContent("源语言", "源语言");
        retVal[1].minWidth = 50;
        retVal[1].width = 100;
        retVal[1].maxWidth = 200;
        retVal[1].headerTextAlignment = TextAlignment.Left;
        retVal[1].canSort = false;
        retVal[1].autoResize = true;

        retVal[2].headerContent = new GUIContent("值", "内容");
        retVal[2].minWidth = 100;
        retVal[2].width = 260;
        retVal[2].maxWidth = 400;
        retVal[2].headerTextAlignment = TextAlignment.Left;
        retVal[2].canSort = false;
        retVal[2].autoResize = true;


        retVal[3].headerContent = new GUIContent("目标语言", "目标语言");
        retVal[3].minWidth = 60;
        retVal[3].width = 120;
        retVal[3].maxWidth = 300;
        retVal[3].headerTextAlignment = TextAlignment.Left;
        retVal[3].canSort = false;
        retVal[3].autoResize = true;

        retVal[4].headerContent = new GUIContent("状态", "状态");
        retVal[4].minWidth = 60;
        retVal[4].width = 100;
        retVal[4].maxWidth = 600;
        retVal[4].headerTextAlignment = TextAlignment.Left;
        retVal[4].canSort = false;
        retVal[4].autoResize = true;

        retVal[5].headerContent = new GUIContent("翻译结果", "翻译结果");
        retVal[5].minWidth = 60;
        retVal[5].width = 100;
        retVal[5].maxWidth = 300;
        retVal[5].headerTextAlignment = TextAlignment.Left;
        retVal[5].canSort = false;
        retVal[5].autoResize = true;

        return retVal;
    }

#if UNITY_6000_2_OR_NEWER
    protected override TreeViewItem<int> BuildRoot()
#else
    protected override TreeViewItem BuildRoot()
#endif

    {
        return CreateView();
    }

    protected override void RowGUI(RowGUIArgs args)
    {
        for (int i = 0; i < args.GetNumVisibleColumns(); ++i)
            CellGUI(args.GetCellRect(i), args.item as TranslateLanguageInfoTreeViewItem, args.GetColumn(i), ref args);
    }

#if UNITY_6000_2_OR_NEWER
    protected override IList<TreeViewItem<int>> BuildRows(TreeViewItem<int> root)
#else
    protected override IList<TreeViewItem> BuildRows(TreeViewItem root)
#endif

    {
        return base.BuildRows(root);
    }


    #endregion


    #region 方法

#if UNITY_6000_2_OR_NEWER

    public TranslateLanguageInfoListTree(MultiLanguageConfigs multiLanguageConfigs, List<LanguageInfo> languageInfos, SystemLanguage from, SystemLanguage to, TranslateAPI api, bool need_intervene, string vocab_id) : base(new TreeViewState<int>(), new MultiColumnHeader(CreateDefaultMultiColumnHeaderState()))
#else
    public TranslateLanguageInfoListTree(MultiLanguageConfigs multiLanguageConfigs, List<LanguageInfo> languageInfos, SystemLanguage from, SystemLanguage to, TranslateAPI api, bool need_intervene, string vocab_id) : base(new TreeViewState(), new MultiColumnHeader(CreateDefaultMultiColumnHeaderState()))

#endif

    {
        this.multiLanguageConfigs = multiLanguageConfigs;
        this.languageInfos = languageInfos;
        this.from = from;
        this.to = to;

        showAlternatingRowBackgrounds = true;

        this.api = api;
        this.need_intervene = need_intervene;
        this.vocab_id = vocab_id;
    }

    private void CellGUI(Rect cellRect, TranslateLanguageInfoTreeViewItem item, int column, ref RowGUIArgs args)
    {

        if (labelStyle == null)
        {
            labelStyle = new GUIStyle(GUI.skin.label);
            labelStyle.richText = true;
        }

        if (!translateInfos.ContainsKey(item.languageInfo.id))
            translateInfos.Add(item.languageInfo.id, new TranslateLanguageInfo(item.languageInfo, multiLanguageConfigs, from, to));

        TranslateLanguageInfo translateInfo = translateInfos[item.languageInfo.id];

        switch (column)
        {
            case 0: // id
                EditorGUI.LabelField(cellRect, item.languageInfo.id.ToString());
                break;
            case 1: // 源语言 
                EditorGUI.LabelField(cellRect, from.ToString());
                break;

            case 2: // 值

                LanguageConfig languageConfig = multiLanguageConfigs.GetLanguageConfigData(from);
                LanguageInfo languageInfo = languageConfig.GetLanguageInfo(item.languageInfo.id);

                EditorGUI.LabelField(cellRect, languageInfo.str);
                break;

            case 3: // 目标语言
                EditorGUI.LabelField(cellRect, to.ToString());
                break;

            case 4: // 状态

                switch (translateInfo.state)
                {
                    case TranslateState.Wait:
                        EditorGUI.LabelField(cellRect, "等待...");
                        break;
                    case TranslateState.InTranslation:
                        EditorGUI.LabelField(cellRect, "翻译中...");
                        break;
                    case TranslateState.Completed:

                        // 判断是否成功 
                        switch (translateInfo.api)
                        {
                            case TranslateAPI.Baidu:

                                if (translateInfo.baidu_result != null)
                                {
                                    EditorGUI.SelectableLabel(cellRect, translateInfo.baidu_result.isError ? translateInfo.baidu_result.error : "成功!");
                                }
                                else
                                {
                                    EditorGUI.SelectableLabel(cellRect, "翻译失败,请稍后重试!");
                                }

                                break;
                            case TranslateAPI.Youdao:

                                if (translateInfo.youdao_result != null)
                                {
                                    EditorGUI.SelectableLabel(cellRect, translateInfo.youdao_result.isError ? translateInfo.youdao_result.error : "成功!");
                                }
                                else
                                {
                                    EditorGUI.SelectableLabel(cellRect, "翻译失败,请稍后重试!");
                                }

                                break;
                        }

                        break;
                }

                break;

            case 5: // 翻译结果 

                switch (translateInfo.api)
                {
                    case TranslateAPI.Baidu:

                        if (translateInfo.baidu_result != null)
                            EditorGUI.LabelField(cellRect, translateInfo.baidu_result.result);

                        break;
                    case TranslateAPI.Youdao:

                        if (translateInfo.youdao_result != null)
                            EditorGUI.LabelField(cellRect, translateInfo.youdao_result.result);

                        break;
                }

                break;

        }
    }

#if UNITY_6000_2_OR_NEWER 
    private TreeViewItem<int> CreateView()
#else
    private TreeViewItem CreateView()
#endif
    {

#if UNITY_6000_2_OR_NEWER
        TreeViewItem<int> root = new TreeViewItem<int>(0, -1);
#else
        TreeViewItem root = new TreeViewItem(0, -1);
#endif


        translateInfos.Clear();

        foreach (var item in languageInfos)
        {
            TranslateLanguageInfoTreeViewItem languageInfoTreeViewItem = new TranslateLanguageInfoTreeViewItem(item);
            root.AddChild(languageInfoTreeViewItem);

            translateInfos.Add(item.id, new TranslateLanguageInfo(item, multiLanguageConfigs, from, to));
        }


        return root;
    }

    public override void OnGUI(Rect rect)
    {
        base.OnGUI(rect);
        Update();

        Rect r = rect;
        r.y += rect.height;
        r.height = 25;
      
       

        if (AllCompleted())
        {
            if (HaveError())
            {
                r.width = 80;
                if (GUI.Button(r,"再试一次"))
                {
                    foreach (var item in translateInfos.Values)
                    {
                        if (item.IsError()) item.Retry();
                    }
                }

                r.x += r.width;

                r.width = 300;

                EditorGUI.BeginDisabledGroup(true);
                GUI.Label(r,"部分翻译出错,可多试几次!");
                EditorGUI.EndDisabledGroup();
               
            }
            else
            {
                r.width = 300;
                EditorGUI.BeginDisabledGroup(true);
                GUI.Label(r,"已全部翻译完成!");
                EditorGUI.EndDisabledGroup();
            }
        }
        else
        {
            r.width = 300;
            GUI.Label(r,"正在翻译中...");
        }
         


    }

    private void Update()
    {

        // 刷新   

        foreach (var item in translateInfos.Values)
        {
            item.Update();
        }


        if (AllRequest())
            return;

        if (GetRequestingCount() < 20)
        {
            // 继续翻译  
            foreach (var item in translateInfos.Values)
            {
                if (item.state == TranslateState.Wait)
                    item.Translate(api, need_intervene, vocab_id);
            }

        }

    }

    private bool AllRequest()
    {
        foreach (var item in translateInfos.Values)
        {
            if (item.state == TranslateState.Wait) return false;
        }

        return true;
    }

    private int GetRequestingCount()
    {
        int count = 0;

        foreach (var item in translateInfos.Values)
        {
            if (item.state == TranslateState.InTranslation)
                count++;
        }

        return count;
    }

    private bool AllCompleted()
    {
        foreach (var item in translateInfos.Values)
        {
            if (item.state != TranslateState.Completed)
                return false;
        }

        return true;
    }

    private bool HaveError()
    {
        foreach (var item in translateInfos.Values)
        {
            if (item.IsError())
                return true;
        }

        return false;
    }

#endregion

}


/// <summary>
/// 一键翻译(翻译某一个语言的所有配置)
/// </summary>
public class TranslateOptionWindow : EditorWindow
{
    private MultiLanguageConfigs multiLanguageConfigs;

    private LanguageConfig fromConfig;
    private LanguageConfig toConfig;


    private SystemLanguage from;

    private SystemLanguage to;

    private GUIContent fromContent;
    private GUIContent toContent;

    private GUIStyle dropdownStyle;

    private TranslateType type;

    private Vector2 scrollPosition;

    private bool in_translation = false;

    private List<LanguageInfo> translateInfos = new List<LanguageInfo>();

    private TranslateLanguageInfoListTree translateLanguageInfoListTree;


    private TranslateAPI api;

    // 术语表
    private bool need_intervene = true;

    // 术语表id
    private string vocab_id;

    private float lastRepaintCount;


    public void ShowOption(MultiLanguageConfigs multiLanguageConfigs, SystemLanguage to)
    {
        this.multiLanguageConfigs = multiLanguageConfigs;
        this.to = to;

        fromConfig = multiLanguageConfigs.GetLanguageConfigData(LocalizationManager.Language);

        if (fromConfig != null && LocalizationManager.Language != to)
        {
            from = LocalizationManager.Language;
        }
        else
        {
            foreach (var item in multiLanguageConfigs.Languages)
            {
                if (item.language == to) continue;
                fromConfig = item;
                from = item.language;
                break;
            }
        }

        toConfig = multiLanguageConfigs.GetLanguageConfigData(to);

        type = TranslateType.Empty;

        in_translation = false;
    }


    private void OnGUI()
    {
        if (multiLanguageConfigs == null)
        {
            Close();
            return;
        }

        scrollPosition = GUILayout.BeginScrollView(scrollPosition);

        OnGUI_From();

        OnGUI_To();

        OnGUI_Type();

        OnGUI_Api();

        OnGUI_Intervene();

        if (!in_translation)
        {
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("开始翻译"))
            {
                StartTranslate();
            }
            GUILayout.Space(20);
        }
        else
        {
            if (translateLanguageInfoListTree != null)
            {
                Rect rect = GUILayoutUtility.GetRect(0, 300);
                rect.height = position.height - rect.y - 25;

                translateLanguageInfoListTree.OnGUI(rect);
            }
            else
            {
                Close();
            }
        }

        GUILayout.EndScrollView();
    }

    private void OnGUI_From()
    {
        if (fromContent == null)
            fromContent = new GUIContent();

        fromContent.text = from.ToString();

        EditorGUILayout.LabelField(string.Empty, "源语言", "BoldLabel");

        if (dropdownStyle == null)
            dropdownStyle = new GUIStyle("DropDown");


        GUILayout.BeginHorizontal();

        EditorGUILayout.LabelField("from", GUILayout.Width(148));

        Rect r = GUILayoutUtility.GetRect(fromContent, dropdownStyle, GUILayout.ExpandWidth(true));
        if (EditorGUI.DropdownButton(r, fromContent, FocusType.Passive, dropdownStyle))
        {
            GenericMenu menu = new GenericMenu();

            foreach (var item in multiLanguageConfigs.Languages)
            {
                if (item.language == to)
                {
                    menu.AddDisabledItem(new GUIContent(item.language.ToString()));
                }
                else
                {
                    menu.AddItem(new GUIContent(item.language.ToString()), from == item.language, () =>
                    {
                        from = item.language;
                    });
                }

            }

            menu.DropDown(r);
        }

        GUILayout.EndHorizontal();
    }

    private void OnGUI_To()
    {

        GUILayout.Space(5);

        if (toContent == null)
            toContent = new GUIContent();

        toContent.text = to.ToString();

        EditorGUILayout.LabelField(string.Empty, "目标语言", "BoldLabel");

        if (dropdownStyle == null)
            dropdownStyle = new GUIStyle("DropDown");

        EditorGUI.BeginDisabledGroup(true);

        GUILayout.BeginHorizontal();

        EditorGUILayout.LabelField("to", GUILayout.Width(148));

        Rect r = GUILayoutUtility.GetRect(toContent, dropdownStyle, GUILayout.ExpandWidth(true));
        EditorGUI.DropdownButton(r, toContent, FocusType.Passive, dropdownStyle);

        GUILayout.EndHorizontal();

        EditorGUI.EndDisabledGroup();
    }


    private void OnGUI_Type()
    {
        GUILayout.Space(5);
        EditorGUILayout.LabelField(string.Empty, "翻译选项", "BoldLabel");
        type = (TranslateType)EditorGUILayout.EnumPopup("type", type);
    }

    private void OnGUI_Api()
    {
        GUILayout.Space(5);
        EditorGUILayout.LabelField(string.Empty, "翻译Api", "BoldLabel");
        api = (TranslateAPI)EditorGUILayout.EnumPopup("api", api);
    }

    private void OnGUI_Intervene()
    {
        GUILayout.Space(5);

        switch (api)
        {
            case TranslateAPI.Baidu:
                EditorGUILayout.LabelField(string.Empty, "术语表", "BoldLabel");
                need_intervene = EditorGUILayout.Toggle("need_intervene", need_intervene);
                break;
            case TranslateAPI.Youdao:
                EditorGUILayout.LabelField(string.Empty, "术语表id", "BoldLabel");
                vocab_id = EditorGUILayout.TextField("vocab_id", vocab_id);
                break;
        }

    }

    private void StartTranslate()
    {

        // 检测密钥 和 key 

        switch (api)
        {
            case TranslateAPI.Baidu:
                if (string.IsNullOrEmpty(LocalizationSettings.Instance.baidu.app_id) || string.IsNullOrEmpty(LocalizationSettings.Instance.baidu.secret_key))
                {
                    if( EditorUtility.DisplayDialog("提示", "app_id 或 密钥为空,请设置后再试!", "打开设置"))
                        LocalizationSettings.Instance.OpenProjectSettings("XFGameFramework/Localization");
                    return;
                }
                break;
            case TranslateAPI.Youdao:

                if (string.IsNullOrEmpty(LocalizationSettings.Instance.youdao.app_id) || string.IsNullOrEmpty(LocalizationSettings.Instance.youdao.secret_key))
                {
                    if(EditorUtility.DisplayDialog("提示", "app_id 或 密钥为空,请设置后再试!", "打开设置"))
                        LocalizationSettings.Instance.OpenProjectSettings("XFGameFramework/Localization");
                    return;
                }

                break;
        }

        // 收集所有需要翻译的内容 
        translateInfos.Clear();

        foreach (var languageInfo in toConfig.languagesInfo)
        {
            if (languageInfo.type != MultiLanguageType.String) continue;

            LanguageInfo fromInfo = fromConfig.GetLanguageInfo(languageInfo.id);

            // 源语言的str为空 直接跳过
            if (string.IsNullOrEmpty(fromInfo.str)) continue;

            switch (type)
            {
                case TranslateType.Empty:

                    if (string.IsNullOrEmpty(languageInfo.str))
                        translateInfos.Add(languageInfo);

                    break;
                case TranslateType.All:
                    translateInfos.Add(languageInfo);
                    break;
            }
        }

        if (translateInfos.Count == 0)
        {
            ShowNotification(new GUIContent("未查询到需要翻译的内容!"));
            return;
        }

        in_translation = true;

        // 显示翻译信息
        if (translateLanguageInfoListTree == null)
        {
            translateLanguageInfoListTree = new TranslateLanguageInfoListTree(multiLanguageConfigs, translateInfos, from, to, api, need_intervene, vocab_id);
            translateLanguageInfoListTree.Reload();
        }

    }


    private void Update()
    {
        lastRepaintCount++;
        if (lastRepaintCount > 15) 
        {
            Repaint();
            lastRepaintCount = 0;
        }

    }

}
